package com.sum.tea.xinlian.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pow.api.cls.RfidPower
import com.sum.tea.contants.AppConfig
import com.uhf.api.cls.R2000Command
import com.uhf.api.cls.Reader
import com.zguang.api.comm.linuxcomm
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.io.InputStream

class UpdateViewModel : ViewModel() {
    private val _progress = MutableLiveData<Float>()
    val progress: LiveData<Float> = _progress

    private val _statusMessage = MutableLiveData<String?>()
    val statusMessage: LiveData<String?> = _statusMessage

    private val _fileExtension = MutableLiveData<String>()
    val fileExtension: LiveData<String> = _fileExtension

    private var mAppConfig = AppConfig()

    fun setFileExtension(extension: String) {
        _fileExtension.value = extension
    }

    fun startUpdate(filename: String) {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                val serialportPath = if (mAppConfig.Rpower.GetType() != RfidPower.PDATYPE.NONE) {
                    mAppConfig.Rpower.GetDevPath()
                } else {
                    mAppConfig.Address
                }
                var baudrate = mAppConfig.Baudrate
                mAppConfig.Mreader?.takeIf { mAppConfig.haveinit }?.CloseReader()
                mAppConfig.Rpower.PowerUp()
                var err = Reader.READER_ERR.MT_OK_ERR
                var errmsg = ""

                if (_fileExtension.value == "mdfw") {
                    err = Reader.FirmwareLoadFromSerialPort(serialportPath, filename)
                } else {
                    val lreader = linuxcomm()
                    try {
                        val parscom: Array<String>? = serialportPath.takeIf { it.contains(":") }?.split(":")?.toTypedArray()
                        val devstr = parscom?.get(0)?.trim() ?: serialportPath
                        baudrate = parscom?.getOrNull(1)?.toInt() ?: baudrate
                        val re = lreader.OpenComm(devstr, baudrate)
                        if (re != 0) throw Exception("openserial err: $re $devstr $baudrate")
                        lreader.InitStream()
                        val field = R2000Command::class.java.getField("is")
                        field.set(null, lreader.inputStream)
                        R2000Command.os = lreader.outputStream

                        val threadEx = arrayOfNulls<Exception>(1)
                        val finalVal = FloatArray(1)

                        viewModelScope.launch(Dispatchers.IO) {
                            try {
                                R2000Command.Updatebyserial(filename, finalVal)
                            } catch (e: Exception) {
                                threadEx[0] = e
                            }
                        }

                        do {
                            threadEx[0]?.let { throw it }
                            if (finalVal[0] >= 1) break
                            _progress.postValue(finalVal[0] * 100)
                            delay(500)
                        } while (true)

                    } catch (ex: Exception) {
                        err = Reader.READER_ERR.MT_OTHER_ERR
                        errmsg = "($baudrate) ${ex.message}"
                    } finally {
                        val field = R2000Command::class.java.getField("is")
                        val inputStream = field.get(null) as? InputStream
                        inputStream?.close()
                        R2000Command.os?.close()
                        lreader.CloseComm()
                    }
                }

                val message = if (err != Reader.READER_ERR.MT_OK_ERR) {
                    "失败: $err $errmsg"
                } else {
                    "成功:请重新连接读写器: $err"
                }
                _statusMessage.postValue(message)
            } catch (e: Exception) {
                _statusMessage.postValue(e.toString())
            }
        }
    }
}

